﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ICSharpCode.TextEditor.Gui.CompletionWindow;
using ICSharpCode.TextEditor;
using System.Windows.Forms;
using ICSharpCode.TextEditor.Document;
using System.Xml.Linq;
using System.IO;
using tiDE.Runtime;

namespace tiDE.CodeCompletion
{
    public class TIBasicCodeCompletion : IInternalCompletionProvider
    {
        public char[] CodeCompletionTriggers
        {
            get
            {
                return "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789>".ToCharArray();
            }
        }

        public int DefaultIndex
        {
            get { return 0; }
        }

        XDocument tiBasicTokens = null;

        public ICompletionData[] GenerateCompletionData(string fileName, ICSharpCode.TextEditor.TextArea textArea, char charTyped)
        {
            try
            {
                List<ICompletionData> CompletionData = new List<ICompletionData>();
                LineSegment segment = textArea.Document.GetLineSegmentForOffset(textArea.Caret.Offset);
                string line = textArea.Document.TextContent.Substring(segment.Offset, segment.Length);
                int index = textArea.Caret.Offset - segment.Offset;
                int lineLength = line.Length;
                line = line.TrimStart();
                index -= (lineLength - line.Length);
                line = line.Trim() + charTyped;

                if (tiBasicTokens == null)
                {
                    Stream stream = File.Open(RuntimeData.tiDEDirectory + "\\CodeCompletion\\Tokens.xml", FileMode.Open);
                    tiBasicTokens = XDocument.Load(stream);
                    stream.Close();
                }

                return GenerateDataRecursive(tiBasicTokens.Root, line);
            }
            catch
            {
                return new ICompletionData[0];
            }
        }

        ICompletionData[] GenerateDataRecursive(XElement Element, string line)
        {
            List<ICompletionData> data = new List<ICompletionData>();

            foreach (XElement element in Element.Elements("Token"))
            {
                if (element.Attribute("string") != null)
                {
                    if (element.Attribute("string").Value.ToLower().StartsWith(line.ToLower()))
                    {
                        string actualValue = element.Attribute("string").Value;
                        foreach (XElement subElement in element.Elements("Alt"))
                        {
                            foreach (char c in subElement.Attribute("string").Value)
                            {
                                if (!char.IsLetterOrDigit(c) && c != '-')
                                {
                                    actualValue = subElement.Attribute("string").Value;
                                    break;
                                }
                            }
                        }
                        data.Add(new TIBasicCodeCompletionData()
                        {
                            Description = actualValue + "\n\nDocumentation to come later",
                            ActualValue = actualValue,
                            Text = actualValue,
                            ImageIndex = 0,
                            Priority = 1,
                        });
                    }
                }
                GenerateDataRecursive(element, line);
            }

            return data.ToArray();
        }

        public ImageList ImageList
        {
            get 
            {
                System.Windows.Forms.ImageList imageList = new ImageList();
                imageList.Images.Add(global::tiDE.Properties.Resources.stock_compile);
                return new ImageList();
            }
        }

        public bool InsertAction(ICompletionData data, TextArea textArea, int insertionOffset, char key)
        {
            if (key == ' ' || key == '(')
                return false;
            try
            {
                textArea.Caret.Position = textArea.Document.OffsetToPosition(insertionOffset);
                string newContent = textArea.Document.TextContent;
                LineSegment segment = textArea.Document.GetLineSegmentForOffset(textArea.Caret.Offset);
                string line = textArea.Document.TextContent.Substring(segment.Offset, segment.Length);
                int index = textArea.Caret.Offset - segment.Offset;
                int length = line.Length;
                line = line.Trim();
                if (line.Contains("("))
                    line = line.Substring(line.IndexOf("(") + 1);
                if (line.Contains(","))
                    line = line.Substring(line.Remove(index).IndexOf(",") + 1);
                line = line.Trim();
                index -= (length - line.Length);
                TIBasicCodeCompletionData tibData = data as TIBasicCodeCompletionData;
                newContent = newContent.Remove(textArea.Caret.Offset - index, index);
                newContent = newContent.Insert(textArea.Caret.Offset - index, tibData.ActualValue);
                textArea.Document.TextContent = newContent;
                textArea.Caret.Position = textArea.Document.OffsetToPosition(segment.Offset + (length - line.Length) + tibData.ActualValue.Length);
            }
            catch { }
            return false;
        }

        public string PreSelection
        {
            get
            {
                return null;
            }
        }

        public CompletionDataProviderKeyResult ProcessKey(char key)
        {
            if (char.IsLetterOrDigit(key) || key == '-')
            {
                return CompletionDataProviderKeyResult.NormalKey;
            }
            else
            {
                // key triggers insertion of selected items
                return CompletionDataProviderKeyResult.InsertionKey;
            }
        }

        public string GetToolTip(TextLocation TextLocation, IDocument Document)
        {
            return "";
        }
    }

    public class TIBasicCodeCompletionData : ICompletionData
    {
        public string Description { get; set; }

        public int ImageIndex { get; set; }

        /// <summary>
        /// Used on any alt symbols
        /// </summary>
        public string ActualValue { get; set; }

        public bool InsertAction(TextArea textArea, char ch)
        {
            return false;
        }

        public double Priority { get; set; }

        public string Text { get; set; }
    }
}
